﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using T.ServiceComponent.I18N.Service;
namespace T.FAS.Runtime.Base.Common
{
    public static class FileTool
    {
        #region 文件夹操作
        /// <summary>
        /// 复制到单个文件夹
        /// </summary>
        /// <param name="sourceFolder"></param>
        /// <param name="destinationFolder"></param>
        public static void CopyFolder(string sourceFolder, string destinationFolder, string exceptFolder = "node_modules")
        {
            // 检查源文件夹是否存在
            if (!Directory.Exists(sourceFolder))
            {
                throw new Exception("源文件夹不存在");
            }
            // 创建目标文件夹
            Directory.CreateDirectory(destinationFolder);

            // 获取源文件夹中的文件和子文件夹
            string[] files = Directory.GetFiles(sourceFolder);
            string[] subFolders = Directory.GetDirectories(sourceFolder);

            // 复制文件到目标文件夹
            foreach (string file in files)
            {
                string fileName = Path.GetFileName(file);
                string destinationPath = Path.Combine(destinationFolder, fileName);
                File.Copy(file, destinationPath, true);
            }

            // 递归复制子文件夹及其内容
            foreach (string subFolder in subFolders)
            {
                string folderName = Path.GetFileName(subFolder);
                if (folderName == exceptFolder)
                {
                    continue;
                }
                string destinationPath = Path.Combine(destinationFolder, folderName);
                CopyFolder(subFolder, destinationPath);
            }
        }
        public static void DeleteFile(string filePath)
        {
            try
            {

                if (File.Exists(filePath))
                    File.Delete(filePath);
            }
            catch(Exception e) 
            {
                LogUtil.Log(e.ToString(),"File");
            }
        }
        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="folderPath"></param>
        public static void DeleteFolder(string folderPath, string exceptFolder = "", string exceptFile = "")
        {
            if (Directory.Exists(folderPath))
            {
                string[] files = Directory.GetFiles(folderPath);
                string[] subFolders = Directory.GetDirectories(folderPath);

                // 复制文件到目标文件夹
                foreach (string file in files)
                {
                    if (file == exceptFile)
                        continue;
                    File.Delete(file);
                }

                // 递归复制子文件夹及其内容
                foreach (string subFolder in subFolders)
                {
                    if (subFolder == exceptFolder)
                        continue;
                    Directory.Delete(subFolder, true);
                }
            }
        }
        /// <summary>
        /// 创建文件夹
        /// </summary>
        /// <param name="path"></param>
        public static void CkeckAndCreatePath(string path)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
        }
        #endregion
        #region 文件操作
        /// <summary>
        /// 压缩文件
        /// </summary>
        /// <param name="zipFileName"></param>
        /// <param name="filePath"></param>
        public static void ZipFile(string zipFileName, string filePath)
        {
            if (File.Exists(zipFileName))
            {
                File.Delete(zipFileName);
            }
            ZipManager.ZipFolderWithoutBaseDirectory(filePath, zipFileName);
            Directory.Delete(filePath, true);
        }
        /// <summary>
        /// 解压文件
        /// </summary>
        /// <param name="zipFileName">文件全路径</param>
        /// <returns></returns>
        public static string UnZipedFile(string zipFileName)
        {
            if (!File.Exists(zipFileName))
            {
                throw new Exception("文件不存在：" + zipFileName);
            }
            var extFilePath = Path.Combine(Path.GetDirectoryName(zipFileName), "UnZipedFiles\\");
            ICSharpCode.SharpZipLib.Zip.FastZip zip = new ICSharpCode.SharpZipLib.Zip.FastZip();
            zip.RestoreDateTimeOnExtract = true;
            zip.RestoreAttributesOnExtract = true;
            zip.ExtractZip(zipFileName, extFilePath, "");
            return Path.Combine(extFilePath, Path.GetFileName(zipFileName).Replace(".zip", ""));
        }
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <exception cref="Exception"></exception>
        public static void SaveFile(string content, string path, string md5)
        {
            if (string.IsNullOrEmpty(content) || string.IsNullOrEmpty(path))
                return;
            var directory = Path.GetDirectoryName(path);
            CkeckAndCreatePath(directory);
            int BufferSize = 1024 * 8;
            using (var file = new FileStream(path, System.IO.FileMode.Create))
            {
                byte[] buff = new byte[BufferSize];

                StringBuilder sb = new StringBuilder(content);

                int bufLenght = Convert.ToBase64String(buff).Length;
                int startindex = 0;

                //大于缓存数组大小的时候
                while (sb.Length - startindex >= bufLenght)
                {
                    buff = Convert.FromBase64String(sb.ToString(startindex, bufLenght));
                    //写入流
                    file.Write(buff, 0, buff.Length);
                    startindex += bufLenght;
                }

                //小于缓存数组的时候
                if (sb.Length - startindex > 0)
                {
                    buff = Convert.FromBase64String(sb.ToString(startindex, sb.Length - startindex));
                    file.Write(buff, 0, buff.Length);
                }
            }
            if (!string.IsNullOrEmpty(md5))
            {
                string newMd5 = GetMD5(path);
                if (newMd5 != md5)
                    throw new Exception("下载的文件不完整，MD5码不一致" + path);
            }
        }
        /// <summary>
        /// 读取文件最后指定行
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="lines"></param>
        /// <returns></returns>
        public static string GetFileText(string filePath, int lines)
        {
            if (!File.Exists(filePath))
                return null;
            try
            {
                StringBuilder text = new StringBuilder();
                List<string> fileContent = new List<string>();
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        // 定位到文件末尾
                        string line = "0";
                        while (line != null)
                        {
                            line = sr.ReadLine();
                            fileContent.Add(line);
                        }
                    }
                }
                int start = fileContent.Count > lines ? fileContent.Count - lines : 0;
                if (lines == 0)
                    start = 0;
                for (int i = start; i < fileContent.Count; i++)
                {
                    text.AppendLine(fileContent[i]);
                }
                return text.ToString();
            }
            catch (Exception e)
            {
                return null;
            }
        }
        /// <summary>
        /// 获取文本内容
        /// </summary>
        /// <param name="path"></param>
        /// <param name="md5"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static string GetFileContent(string path, out string md5)
        {
            if (!File.Exists(path))
                throw new Exception("指定的文件路径不存在：" + path);
            md5 = GetMD5(path);
            int BufferSize = 1024 * 8;
            using (FileStream file = new FileStream(path, System.IO.FileMode.Open))
            {
                byte[] buff = null;
                StringBuilder rtnvalue = new StringBuilder(1000);

                System.IO.BinaryReader br = new System.IO.BinaryReader(file);
                do
                {
                    buff = br.ReadBytes(BufferSize);
                    rtnvalue.Append(Convert.ToBase64String(buff));

                } while (buff.Length != 0);
                return rtnvalue.ToString();
            }
        }
        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string GetMD5(Stream stream)
        {
            using (stream)
            {
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(stream);
                return GetMD5ByHash(retVal);
            }
        }
        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string GetMD5(byte[] byteContent)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(byteContent);
            return GetMD5ByHash(retVal);
        }
        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string GetMD5(string filePath)
        {
            byte[] retVal = null;
            using (FileStream file = new FileStream(filePath, FileMode.Open))
            {
                MD5 md5 = new MD5CryptoServiceProvider();
                retVal = md5.ComputeHash(file);
            }
            return GetMD5ByHash(retVal);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="retVal"></param>
        /// <returns></returns>
        private static string GetMD5ByHash(byte[] retVal)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }
        #endregion
        #region 资源服务
        /// <summary>
        /// 转换文件名称 资源服务用
        /// </summary>
        /// <param name="metaDataName"></param>
        /// <returns></returns>
        public static string GetFileName(string metaDataName)
        {
            string[] notCodes = new string[5] { "_", "+", "&", "%", "/" };
            foreach (var notCode in notCodes)
            {
                metaDataName = metaDataName.Replace(notCode, "");
            }
            return metaDataName;
        }
        /// <summary>
        /// 加载文件
        /// </summary>
        /// <returns></returns>
        public static void LoadFile(string fileURL)
        {
            using (HttpClient httpClient = new HttpClient())
            {
                var url = ConfigUtil.Instance.ResourceAPIDomain + "/" + fileURL;
                //下载图片的地址，发送请求
                using (HttpResponseMessage response = httpClient.GetAsync(url).Result)
                {
                    response.EnsureSuccessStatusCode();
                }
            }
        }
        /// <summary>
        /// 上传单个文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="json"></param>
        /// <param name="file"></param>
        public static string UploadFile(string fileName, MultipartFormDataContent formData)
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Add("SessionId", "00000000-0000-0000-0000-000000000000");
                var url = ConfigUtil.Instance.ResourceAPIDomain + "/api/resource/UploadDocByMultipart";
                using (var response = httpClient.PostAsync(url, formData).Result)
                {
                    response.EnsureSuccessStatusCode();
                    var result = response.Content.ReadAsStringAsync().Result;
                    UploadResult uploadResult = JsonConvert.DeserializeObject<UploadResult>(result);
                    if (uploadResult.Code != "000")
                    {
                        throw new Exception(GetUploadMsg(uploadResult.Code));
                    }
                    return uploadResult.RelativeUrls[0];
                }
            }
        }
        /// <summary>
        /// 上传单个文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="json"></param>
        /// <param name="file"></param>
        public static UploadResult UploadFile(string fileName, string json, string file)
        {
            using (var httpClient = new HttpClient())
            {
                //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

                httpClient.DefaultRequestHeaders.Add("SessionId", "00000000-0000-0000-0000-000000000000");
                MultipartFormDataContent formData = new MultipartFormDataContent();
                StringContent content = new StringContent(json, Encoding.UTF8, "application/json");
                ByteArrayContent fileContent = new ByteArrayContent(Encoding.UTF8.GetBytes(file));
                formData.Add(content, fileName);
                formData.Add(fileContent, fileName, fileName);
                var url = ConfigUtil.Instance.ResourceAPIDomain + "/api/resource/UploadDocByMultipart";
                using (var response = httpClient.PostAsync(url, formData).Result)
                {
                    response.EnsureSuccessStatusCode();
                    var result = response.Content.ReadAsStringAsync().Result;
                    UploadResult uploadResult = JsonConvert.DeserializeObject<UploadResult>(result);
                    if (uploadResult.Code != "000")
                    {
                        throw new Exception(GetUploadMsg(uploadResult.Code));
                    }
                    return uploadResult;
                }
            }
        }
        /// <summary>
        /// 批量上传
        /// </summary>
        /// <param name="formData"></param>
        public static UploadResult UploadFiles(MultipartFormDataContent formData)
        {
            using (var httpClient = new HttpClient())
            {
                httpClient.DefaultRequestHeaders.Add("SessionId", "00000000-0000-0000-0000-000000000000");
                var url = ConfigUtil.Instance.ResourceAPIDomain + "/api/resource/UploadDocByMultipart";
                using (var response = httpClient.PostAsync(url, formData).Result)
                {
                    HttpResponseMessage httpResponseMessage = response.EnsureSuccessStatusCode();
                    var result = response.Content.ReadAsStringAsync().Result;
                    UploadResult uploadResult = JsonConvert.DeserializeObject<UploadResult>(result);
                    if (uploadResult.Code != "000")
                    {
                        throw new Exception(GetUploadMsg(uploadResult.Code));
                    }
                    return uploadResult;
                }
            }
        }
        /// <summary>
        /// 获取上传错误码
        /// </summary>
        /// <param name="resultCode"></param>
        /// <returns></returns>
        public static string GetUploadMsg(string resultCode)
        {
            switch (resultCode)
            {
                case "001":
                    return $"{TermService.Current.GetText("T_FAS_fasr_Base_590562917", "上传内容无效")}";
                case "002":
                    return $"{TermService.Current.GetText("T_FAS_fasr_Base_171062805", "不支持的资源类型（后缀名）或PathId格式错误")}";
                case "003":
                    return $"{TermService.Current.GetText("T_FAS_fasr_Base_808896272", "上传文件服务器出错")}";
                case "004":
                    return $"{TermService.Current.GetText("T_FAS_fasr_Base_1791599241", "文件名超出最大长度或文件名包含不支持的字符")}";
                default:
                    return $"{TermService.Current.GetText("T_FAS_fasr_Base_340096833", "上传文件失败")}";
            }
        }
        #endregion
    }
}
